package service

import (
	"crypto/md5"
	"encoding/hex"
	"entrytask/facade"
	errno "entrytask/pkg/error"
	"entrytask/rpc/dal"
	"fmt"
	"log"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

// UserLogin 用户登录暴露方法: "Login"
// return user User, err int
// user:	成功则返回更新后的用户信息
// token:	登录成功之后返回token
func UserLogin(request *facade.UserLoginRequest) (user *facade.User, token string, err *errno.Errno) {
	start := time.Now().UnixNano()
	defer consumeTime(start, facade.Login)

	/*
		errs = userDal.SelectUserByName(request.Username)
		if errs != nil {
			return &facade.User{}, "", errno.ErrUserNotFound
		}
		if userDal.UserName == "" {
			return &facade.User{}, "", errno.ErrUserNotFound
		}
		// 校验账号密码是否正确
		encoded := dal.SelectPassword(request.Password)
		if strings.Compare(encoded, userDal.Password) != 0 { // 密码不正确
			return &facade.User{}, "", errno.ErrPasswordIncorrect
		}
	*/

	// 校验用户是否存在以及校验密码
	userDal := dal.User{}
	check, errs := userDal.SelectUserWithCheckPassWordByName(request.Username, request.Password)
	if errs != nil || userDal.UserName == "" {
		return &facade.User{}, "", errno.ErrUserNotFound
	}
	// 密码不正确
	if !check {
		return &facade.User{}, "", errno.ErrPasswordIncorrect
	}

	// 缓存token与用户名映射，便于登陆态校验 fixme 多次请求会多次缓存
	token = generateToken(request.Username)
	go CacheTokenForUser(token, request.Username)

	// 缓存用户信息到redis，便于下次查询
	go cacheUserInfo(&userDal)

	return userConverter(userDal), token, errno.OK
}

// UserQueryByName 查询用户信息暴露方法: "QueryUser"
// return user User, err int
// user:	返回用户详细信息
func UserQueryByName(username string) (user *facade.User, err *errno.Errno) {
	start := time.Now().UnixNano()
	defer consumeTime(start, facade.QueryName)
	// 先从缓存中取数据，存在则直接返回
	userDal := GetUserInfo(username)
	if userDal != nil {
		return userConverter(*userDal), errno.OK
	}
	// 不存在从数据库中取，并放入缓存
	userDal = &dal.User{}
	err2 := userDal.SelectUserByName(username)
	if err2 != nil || userDal.UserName == "" {
		return &facade.User{}, errno.ErrUserNotFound
	}
	// 缓存用户信息到redis
	go cacheUserInfo(userDal)

	log.Println("rpc server UserQueryByName response, ", username)
	return userConverter(*userDal), errno.OK
}

// UserQueryByToken 查询用户信息暴露方法: "QueryUserByToken"
// return user User, err BizError
// user:	返回用户详细信息
func UserQueryByToken(token string) (user *facade.User, err *errno.Errno) {
	// 根据token从缓存中取username (todo token 校验)
	username := GetUserNameFromToken(token)
	if username == "" {
		return &facade.User{}, errno.ErrUserNotFound
	}
	// 根据用户名取用户信息
	log.Println("rpc server user query response, ", token)
	return UserQueryByName(username)
}

// UserUpdateInfo 更新用户信息, 包含用户昵称和头像路径
// return user User, errno
// user:	成功则返回更新后的用户信息
func UserUpdateInfo(request *facade.UserUpdateRequest) (user *facade.User, err *errno.Errno) {
	// 校验用户是否存在
	initUser := dal.User{
		UserName: request.Username,
		Nickname: request.Nickname,
		Profile:  request.ProfilePath,
	}
	errs := initUser.SelectUserByName(request.Username)
	if errs != nil || initUser.UserName == "" {
		return &facade.User{}, errno.ErrUserNotFound
	}

	nums := initUser.UpdateUserByName(request.Username, request.Nickname, request.ProfilePath)

	// 删除缓存用户信息
	if nums > 0 {
		go DelUserCache(initUser.UserName)
	}

	fmt.Println("rpc server UserUpdateInfo response, rows affected: ", nums)
	return userConverter(initUser), errno.OK
}

func userConverter(us dal.User) *facade.User {
	return &facade.User{ID: us.Id, Username: us.UserName, Nickname: us.Nickname, Profile: us.Profile}
}

func generateToken(username string) string {
	timestamp := time.Now().Format(time.RFC3339)
	mux := timestamp + strconv.Itoa(rand.Int()) + username
	h := md5.New()
	h.Write([]byte(mux))
	return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}

func cacheUserInfo(user *dal.User) {
	err := CacheUserInfo(user)
	if err != nil {
		log.Println("cache user info to redis fail, ", err)
		recover()
	}
}

func consumeTime(start int64, method string) {
	end := time.Now().UnixNano()
	log.Printf("rpc server method[%s] consume time: %d ns", method, end-start)
}

//func UserLogon(request *facade.UserLogonRequest) (username string, err *errno.Errno) {
//
//	fmt.Println("rpc server UserLogon response, ", request)
//	log.Println("rpc server response, ", request)
//
//	return "goroutine", errno.OK
//}

// UserUpdateProfile 更新用户头像暴露方法: "UpdateNick"
// return user User, err int
// user:	成功则返回更新后的用户信息
//func UserUpdateProfile(request *facade.UserUpdateRequest) (user *facade.User, err *errno.Errno) {
//
//	fmt.Println("rpc server UserUpdateProfile response, ", request)
//	return nil, errno.OK
//}

// UserUpdateNick 更新用户昵称暴露方法: "UpdateProfile"
// return user User, err int
// user:	成功则返回更新后的用户信息
//func UserUpdateNick(request *facade.UserUpdateRequest) (user *facade.User, err *errno.Errno) {
//
//	fmt.Println("rpc server UserUpdateNick response, ", request)
//	return nil, errno.OK
//}
